// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package math

// 下面的原始C代码、长注释和常量
// 来自http:
// 可从http:
// go代码是原始C.
// tanh的简化版本。c 
// 
// 双曲正切
// 
// 简介：
// 
// 双x，y，tanh（）；
// 
// y=tanh（x）；
// 
// 说明：
// 
// 返回MINLOG到MAXLOG范围内参数的双曲正切。
// MAXLOG=8.8029691931113054295988e+01=log（2**127）
// MINLOG=-8.872283911167299960540e+01=log（2**-128）
// 
// 有理函数用于|x |<0.625。采用Cody&Waite的
// x+x**3 P（x）/Q（x）表格。
// 否则，
// tanh（x）=sinh（x）/cosh（x）=1-2/（exp（2x）+1。
// 
// 准确度：
// 
// 相对误差：
// 算术域#试验峰值rms 
// IEEE-2,2 300002.5e-16 5.8e-17 
// 
// Cephes数学库发行版2.8:2000年6月
// 版权所有1984年，1987年，1989年、1992年、2000年由Stephen L.Moshier 
// 
// http:
// 本档案中的一些软件可能来自《数学函数的方法和程序》（Prentice Hall或Simon&Schuster 
// International，1989）一书或Cephes数学图书馆，
// 商业产品。无论哪种情况，它都是作者的版权。
// 您在这里看到的内容可以免费使用，但不提供任何支持或保证。
// 
// 本书中两个已知的印刷错误在这里的
// 伽马函数和不完整的beta 
// 积分的源代码列表中修复。
// 
// Stephen L.Moshier 
// moshier@na-网。奥尔。gov 
// 

var tanhP = [...]float64{
	-9.64399179425052238628e-1,
	-9.92877231001918586564e1,
	-1.61468768441708447952e3,
}
var tanhQ = [...]float64{
	1.12811678491632931402e2,
	2.23548839060100448583e3,
	4.84406305325125486048e3,
}

// Tanh返回x的双曲正切。
// 
// 特殊情况是：
// Tanh（±0）=±0 
// Tanh（±Inf）=±1 
// Tanh NaN=NaN 
func Tanh(x float64) float64 {
	if haveArchTanh {
		return archTanh(x)
	}
	return tanh(x)
}

func tanh(x float64) float64 {
	const MAXLOG = 8.8029691931113054295988e+01 // log（2**127）
	z := Abs(x)
	switch {
	case z > 0.5*MAXLOG:
		if x < 0 {
			return -1
		}
		return 1
	case z >= 0.625:
		s := Exp(2 * z)
		z = 1 - 2/(s+1)
		if x < 0 {
			z = -z
		}
	default:
		if x == 0 {
			return x
		}
		s := x * x
		z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
	}
	return z
}
